﻿
#define A

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TypeCSharp
{    
    /*
     * *************************************************************************************
     * *************************************************************************************
     *                                      IDENTIFICATEUR & TYPE
     * *************************************************************************************
     * *************************************************************************************
    */
    /// <summary>
    /// Classe expliquant les indentificateurs et type en C#
    /// </summary>
    public class IdentificateurEtTypeCSharp
    {

    // Règles sur les indentificateurs (nom de classe, fonction, variable)
    private class IdentificateurCSharp
    {
        private void GetExempleIdent()
        {
            /* 
             * Premier caractère :
             * a-z
             * A-Z
             * à,é,è ...
             * _
            */
            int abc = 0;    abc++;
            int ABC = 0;    ABC++;  
            int àéè = 0;    àéè++;
            int _abc = 0;   _abc++;

            /*
             * Caractères suivants :
             * idem + chiffre
             */

            int _1234 = 0; _1234++;

            /* 
             * Possibilité d'utilisé des mots réservés :
             * si préfixé de @
             */

            int @int =0; @int++;

            /*
             * indentificateur invalide :
             * 1abc
             * A+123
             */
        }
    }

    private class TypeCSharp
    {
        private void UseTypeCSharp()
        {
            // Entier
            byte    e1=0;e1++;  // 0    à 255                           (8 bits/ 1 octet) 
            sbyte   e2=0;e2++;  // -128 à 127                           (8 bits/ 1 octet)

            short   e3=0;e3++;  // -32768   à 32767                     (16 bits/ 2 octets)
            ushort  e4=0;e4++;  // 0        à 65535                     (16 bits/ 2 octets)

            int     e5=0;e5++;  // -2 147 483 648   à 2 147 483 647     (32 bits/ 4 octets)
            uint    e6=0;e6++;  // 0                à 4 294 967 295     (32 bits/ 4 octets)

            long    e7=0;e7++;  // -9.2 *10^18  à  9.2 *10^18           (64 bits/ 8 octets)
            ulong   e8=0;e8++;  // 0            à 18.0 *10^18           (64 bits/ 8 octets)

            // Reel
            float   r1=0;r1++;  // 1.4*10^-45 à 3.4*10^38               (32 bits/ 4 octect)
                                // Précision sur 7 décimale
            double  r2=0;r2++;  // 4.9*10^-324 à 1.8*10^308             (64 bits/ 8 octects)
                                // Précision sur 15 décimale
            decimal r3=0;r3++;  // 4.9*10^-324 à 1.8*10^308             (128 bits/ 16 octects)
                                // Plus précise mais plus lente 
            // Bool
            bool b1=true; b1 = !b1;

            // Texte
            char    c   ='c';c++;       // (16 bits/ 2 octect);
            string  s   ="super";s+=""; // (16 bits/ 2 octect par caractère)
            char    c2  = s[0];
            string  s2  = s;             // Copie des valeurs et non pas des références

            ////////////////////////////
            // CONST : affectation de la valeur seulement à la déclaration de la variable
            const double PI = 3.14;            

            /////////////////////////
            // NULLABLE
            int? i1 = 1;
            int? i2 = null;
            i1++;
            i2++; // Exception

            /////////////////////////
            // VAR
            var i = PI; i++;        // i définit comme int            
            var o = new object();   // o définit comme object

            /////////////////////////
            // ANONYMES : déclaration de classe à l'arache
            var x = new {NOM="Bat", PRENOM="Yan"};

            B b = new B { NOM = "Bat", PRENOM = "Yan" };
            var y = new {b.NOM, b.PRENOM};

            /////////////////////////
            // DYNAMIC :trés couteux en perf
            dynamic d;
            d = 10;
            d = 10.2;
            d = new object();
        }
        public class B
        {
            public string NOM { get; set; }
            public string PRENOM { get; set; }
        }

        // Pb float & double : possibilité d'imprécision (ex : 10 000 * 0.001 = 10.0004)
        private void DisplayPbReel()
        {   
            float f = 0.001F;
            for( int i=1; i<10000; i++)
            {
                f = f+0.001F;
            }

            double d1 = 0.001;
            for( int i=1; i<10000; i++)
            {
                d1 = d1+0.001;
            }

            decimal d2 = 0.001M;
            for( int i=1; i<10000; i++)
            {
                d2 = d2+0.001M;
            }

            Console.WriteLine("CALCUL REEL : 0.001 +0.001 +0.001 ...(10 000 fois)");
            Console.WriteLine("float : {0}", f.ToString());
            Console.WriteLine("double : {0}",d1.ToString());
            Console.WriteLine("decimal : {0}",d2.ToString());
            Console.ReadLine();
        }
    }

    private class ConstanteCSharp
    {

        private void UseConstanteCSharp()
        {

            /*
             * #define (en entête de fichier)
             */

            // si A défini alors execution du code
#if A
            int a=0;a++;
#endif
            // si A non défini alors execution du code
#if !A
            int a=0;a--;
#endif
            Console.WriteLine("char : {0}",a.ToString());
            Console.ReadLine();


            /*
             * Hexadécimale 0x...
             */

            int i = 0x1BAA4;i++; // i = 1*2^12 + 11*2^8 + 10*2^4 + 10*2^2 + 4*2^0

            /*
             * Format 
             */

            long    l=10000L*2; l++; // L pour long sinon pris comme int (par défaut), si nombre rentre dans int sinon auto en long (ex : 10 000 000 000 : pas besoin du L) 
            float   f=1000.00F; f++; // pour les float, le F est obligatoire
            decimal d=10.00M;   d++; // pour les decimal, le M est obligatoire

            /*
             * caratère
             */
            char c  = '\x41';c++;           // caractère A en unicode
            char c2 = '\u0041';c2++;        // caractère A en unicode
            char c3 = '\\';c3++;            // caractère \
            char c4 = '\'';c4++;            // caractère '
            char c5 = '\n';c5++;            // exception \n : retour ligne
            string s1 = "AB\nCD;";s1+="";   // AB + retour ligne + CD
            string s2 = "AB\\nCD;";s2+="";  // contre exception \\, résultat : "AB\nCD"
            string s3 = @"AB\nCD;";s3+="";  // contre exception @, résultat : "AB\nCD"
            string s4 = @"AB
                    CD";s4+="";             // @ seul moyen d'écrire une chaine sur plusieurs ligne
            string s5 = @"AB""CD";s5+="";   // "" pour faire appraitre un " dans chaine avec @
        }
    } 
    }

    

    /*
        * *************************************************************************************
        * *************************************************************************************
        *                                      OPERATEUR
        * *************************************************************************************
        * *************************************************************************************
    */
    /// <summary> OperateurCSharp </summary>
    public class OperateurCSharp
    {
        private void UseOperateur()
        {
            // Opérateur : +, -, *, /, %
            // Opérateur prés ++i, --i et post incrémentation i++, i--
            // Opérateur +=, -=, *=, /=, %=

            // Des incrémentation peuvent faire passer de la valeur la plus haute à la plus basse
            short s=32766;
            s++;Console.WriteLine(s);
            s++;Console.WriteLine(s);
            s++;Console.WriteLine(s);
            
           

            // Ordre de priorité :
            //  double
            //      float
            //          long
            //              int
            //          short
            //      char
            //  byte

            object  res;
            double  b=2;
            float   c=3;
            long    d=4;
            int     e=5;
            res = b*c + d/e ;
            Console.WriteLine("Calcul : {0}, {1}",res, res.GetType());

            object  res2;
            int     f=2;
            short   g=3;
            char    h='4';
            byte    i=2;
            res2 = f*g + h/i;
            Console.WriteLine("Calcul : {0}, {1}",res2, res2.GetType());

            // decimale (ne doit travailler qu'avec des décimale et des entier)
            decimal dec = 3;
            dec = dec * 2; // OK : 2 : entier 
            //dec = dec * 2.0; // KO : 2.0 : double (par défaut), solution :
            dec = dec * 2.0M;  // 2.0 casté en décimale
            dec = (decimal)((double)dec * 2.0); // casté le dec en double poue le *, résultat du * en double ensuite reconverti en decimale

            //short
            short res3, s1=5, s2=6;
            // res3 = s1 - s2; // ATTENTION KO : sans précision le résultat du - passe en int
            res3 = (short)(s1 - s2);

            Console.ReadLine();
        }

        private void UseErreurEntierFloatDecimal()
        {
            ////////////////////////
            // ERREUR SUR ENTIER
            ////////////////////////

            // Pas d'erreur en cas de dépassement de capacité
            int i = 1000000000;
            int j = 10;
            int k = i * j; // Dépassement de cpaciété du int sans erreur
            Console.WriteLine("Calcul : {0}, {1}",k, k.GetType());
            
            // Erreur déclenché manuellement par checked
            try
            {
                checked{ int k2 = i * j; }
            }
            catch(Exception e)
            {
                Console.WriteLine("Exception : {0}",e.GetType());
            }
            
            // Erreur systématique si division par 0 : DivideByZeroException
            try
            {
                int d = 0;
                checked{ int k3 = i / d; }
            }
            catch(DivideByZeroException e)
            {
                Console.WriteLine("Exception : {0}",e.GetType());
            }

            // Pas d'erreur si perte d'info par casting
            try
            {
                short s = (short)i;         // Pas d'erreur
                checked{ s = (short)i; }    // Erreur déclenché manuellement
            }
            catch(Exception e)
            {
                Console.WriteLine("Exception : {0}",e.GetType());
            }

            ////////////////////////
            // ERREUR SUR DECIMAL
            ////////////////////////

            // Idem que ENTIER

            ////////////////////////
            // ERREUR SUR FLOAT & DOUBLE
            ////////////////////////
            double d1, d2=0;
            d1 = 5/d2;
            if( Double.IsInfinity(d1) )
                Console.WriteLine("Infini : {0}, {1}",d1, d1.GetType());

            double d3, d4;
            d4 = Double.MaxValue;
            d3 = d4+2;
            if( Double.IsNegativeInfinity(d3) )
                Console.WriteLine("Infini : {0}, {1}",d3, d3.GetType());

            double d5, d6=2E200, d7=2E300;
            d5 = d6 * d7;
            if( Double.IsInfinity(d5) )
                Console.WriteLine("Infini : {0}, {1}",d5, d5.GetType());
        }

        private void UseOperateurBool()
        {
            // if , !, ||, &&
        }

        private void UseOperateurBinaire()
        {
            // & (AND), | (OR), ^(XOR), ~(inversion), >>, <<
        }

        private void UseOeprateurIsType()
        {
            // GetType() == typeof()
            object i = 10;
            if (i.GetType() == typeof(int))
            {
            }

            // is
            if (i is int)
            {
            }

            // as (transtypage)
            object a = new object();
            object j = a as object;
        }
    }
}
